import { createFilter, normalizePath } from '@rollup/pluginutils'
import fs from 'fs-extra'
import path from 'path'
import { CWD, DEFAULT_ASSETS_INCLUDE_RE } from './constants'
import { compressors } from './minify'
import { UserOptions } from './types'
import { escape, toArray } from './utils'

export const resolveOptions = ({
  publicPath: _publicPath = [],
  include = DEFAULT_ASSETS_INCLUDE_RE,
  exclude,
  inline: _inline = false,
  resolveFileNameExpression = true,
  root: _root = CWD,
  minify: _minify = false,
  target,
  minifyPlugins,
  base,
  native
}: UserOptions = {}) => {
  const root = path.normalize(path.resolve(CWD, _root))
  const publicPath = toArray<string | { [src: string]: string }>(_publicPath)
    .filter(Boolean)
    .reduce<{ [src: string]: string }>((paths, curr) => {
      if (typeof curr === 'object') {
        for (const key in curr) {
          const p = path.normalize(path.resolve(root, key))
          paths[p] = paths[p] || normalizePath(curr[key] ?? '')
        }
      } else {
        const p = path.normalize(path.resolve(root, curr))
        paths[p] = paths[p] || ''
      }
      return paths
    }, Object.create(null))

  const publicPathKey = Object.keys(publicPath)
  const publicPathRe =
    publicPathKey.length > 0 ? new RegExp(`^(${publicPathKey.map(p => escape(p)).join('|')})`) : undefined

  const commonFilter = createFilter(undefined, [/[\0\?]/, ...toArray(exclude)])
  const publicFilter = createFilter(publicPathRe ? publicPathRe : [], [/[\0\?]/, ...toArray(exclude)], {
    resolve: root
  })
  const filter = createFilter(include, [/[\0\?]/, ...toArray(exclude)], {
    resolve: root
  })
  const inline =
    typeof _inline === 'function'
      ? _inline
      : typeof _inline === 'number'
      ? (filename: string) => {
          return fs.statSync(filename).size < (_inline as number) * 1024
        }
      : () => !!_inline

  const minify = typeof _minify === 'function' ? _minify : () => !!_minify

  if (minifyPlugins && typeof minifyPlugins === 'object') {
    for (const [extname, plugin] of Object.entries(minifyPlugins)) {
      if (typeof plugin === 'function') {
        compressors[extname.replace(/^\./, '')] = plugin
      }
    }
  }

  return {
    publicPath,
    publicPathRe,
    resolveFileNameExpression,
    commonFilter,
    publicFilter,
    filter,
    inline,
    target,
    minify,
    base,
    native
  }
}
